<template>
	<page-meta :page-style="'overflow:' + (calendarVisible ? 'hidden' : 'visible')"></page-meta>
	<view class="page-container bg-grey">
		<up-navbar v-bind="navbarProps" @leftClick="pageBack"></up-navbar>
		<ImageSwiper :detail_urls="tripData.detail_urls" dot_position="right" />

		<view
			class="tabs-wrap"
			:style="{ top: tabShow ? commonStore.navbarHeight + commonStore.statusBarHeight + 'px' : 0 }"
			v-if="tabShow"
		>
			<view class="tabs">
				<view
					v-for="item in tabList"
					:key="item.id"
					class="item"
					:class="{ checked: currentTabId === item.id }"
					@click="handleTabClick(item.id)"
				>
					{{ item.text }}
				</view>
			</view>

			<scroll-view class="scroll-view" scroll-x scroll-with-animation :scroll-into-view="scrollIntoViewId">
				<view class="line">
					<view
						v-for="(item, index) in tripData.skus"
						:key="item.id"
						class="line-item"
						:id="`line-item-${index}`"
						:class="{ checked: packageInfo.id === item.id }"
						@click="handleLineItemClick(item, index)"
					>
						线路{{ index + 1 }}
					</view>
				</view>
			</scroll-view>
		</view>

		<TicketInfo
			:display_name="tripData.display_name"
			:sale_tips="tripData.sale_tips"
			:intro="tripData.intro"
			:score_in_cent="tripData.score_in_cent"
			:price_in_cent="priceInfo.price_in_cent"
		/>

		<template v-if="tripData.skus?.length">
			<PlayPackage
				ref="playPackageRef"
				:date="date"
				:skus="tripData.skus"
				@calendar-visible="handleCalendarVisible"
				@price-change="handlePriceChange"
				@package-change="handlePackageChange"
			/>
		</template>

		<view id="itinerary" v-if="packageInfo?.itinerary_infos?.length">
			<Itinerary :business_type="tripData.business_type" :itinerary_infos="packageInfo.itinerary_infos" />
		</view>

		<view id="introduce" v-if="tripData.description">
			<Description :description="tripData.description" @resource-loaded="handleResourceLoaded" />
		</view>

		<view class="card order-notice" id="notice" v-if="packageInfo.booking_tips?.length">
			<NoticeCard :sale_tips="[]" :booking_tips="packageInfo.booking_tips" title="预订须知" />
		</view>

		<RefundRule
			:tourist_refund_fee_rules="packageInfo.tourist_refund_fee_rules"
			:ta_refund_fee_rules="packageInfo.ta_refund_fee_rules"
			:ta_display_penalty="packageInfo.ta_display_penalty"
			:ta_penalty_txt="packageInfo.ta_penalty_txt"
		/>

		<view id="expenses" v-if="packageInfo?.expenses?.length">
			<Expenses :expenses="packageInfo.expenses" />
		</view>

		<Store :store="tripData.store" />

		<PriceDescription />

		<view class="bottom">
			<navigator class="icons" url="/pages/home/index" open-type="switchTab" hover-class="none">
				<image class="home-icon" :src="`${imgBaseUrl}home-icon.png`" />
				<text class="text">首页</text>
			</navigator>
			<view class="btn" :class="{ disabled: !hasPrices }" @click="submit">
				{{ hasPrices ? "立即预定" : "暂不可预定" }}
			</view>
		</view>
	</view>
</template>

<script setup>
import { ref, computed, getCurrentInstance, watchEffect, nextTick } from "vue"
import { onLoad, onPageScroll, onReachBottom } from "@dcloudio/uni-app"
import { pageBack } from "@/utils/page-redirect"
import { $getTripDetail } from "@/api/trip"
import { getIdBYScene } from "@/utils/tools"
import { needLogin } from "@/utils/users"
import useCommonStore from "@/store/common"
import ImageSwiper from "../components/image-swiper.vue"
import TicketInfo from "../components/ticket-info.vue"
import PlayPackage from "./components/play-package.vue"
import Itinerary from "./components/itinerary.vue"
import Description from "../components/description.vue"
import RefundRule from "./components/refund-rule.vue"
import Expenses from "./components/expenses.vue"
import NoticeCard from "../components/notice-card.vue"
import Store from "../components/store.vue"
import PriceDescription from "../components/price-description.vue"
const imgBaseUrl = inject("imgBaseUrl")
const commonStore = useCommonStore()
const instance = getCurrentInstance()
let scroll_top = 0
let timer = null

// 大于 baesTop 才出现 tabs
const baseTop = uni.upx2px(640) - commonStore.navbarHeight - commonStore.statusBarHeight
const backupTabList = [
	{
		id: "itinerary",
		text: "行程",
	},
	{
		id: "introduce",
		text: "介绍",
	},
	{
		id: "notice",
		text: "须知",
	},
	{
		id: "expenses",
		text: "费用",
	},
]

const tripId = ref("")
const date = ref("")
// 选中的套餐
const packageInfo = ref({})
const tripData = ref({})
const tabShow = ref(false)
const calendarVisible = ref(false)
const priceInfo = ref({})
const tabList = ref(backupTabList)
const currentTabId = ref("")
const isTabChange = ref(false)
const playPackageRef = ref(null)
const scrollIntoViewId = ref("")

const navbarProps = computed(() => ({
	"bg-color": tabShow.value ? "#fff" : "transparent",
	title: tabShow.value ? tripData.value.display_name : "",
}))

const hasPrices = computed(() => {
	if (tripData.value.enabled !== 1) return false

	return !priceInfo.isAllNoneSellable
})

const handleCalendarVisible = (visible) => (calendarVisible.value = visible)
const handlePriceChange = (info) => (priceInfo.value = info)
const handlePackageChange = (info) => {
	packageInfo.value = info
}

const handleLineItemClick = (item, idx) => {
	if (packageInfo.value.id === item.id) return

	scrollIntoViewId.value = `line-item-${idx}`

	playPackageRef.value.handlePackageClick(item, idx)
}

const submit = () => {
	if (!hasPrices.value) return

	needLogin(() =>
		uni.navigateTo({
			url: `/pages/product/trip/submit-order?id=${tripId.value}&sku_id=${packageInfo.value.id}&date=${priceInfo.value.date}`,
		})
	)
}

const handleTabClick = (id) => {
	if (currentTabId.value === id) return

	if (timer) clearTimeout(timer)

	isTabChange.value = true

	currentTabId.value = id

	uni.pageScrollTo({
		scrollTop: tabList.value.find((item) => item.id === currentTabId.value).top,
		complete: () => {
			timer = setTimeout(() => {
				isTabChange.value = false
				clearTimeout(timer)
			}, 500)
		},
	})
}

const getDistanceArr = () => {
	return new Promise((resolve) => {
		let list = [...backupTabList]

		if (!packageInfo.value?.itinerary_infos?.length) {
			list = list.filter((item) => item.id !== "itinerary")
		}

		if (!tripData.value?.description) {
			list = list.filter((item) => item.id !== "introduce")
		}

		if (!packageInfo.value?.booking_tips?.length) {
			list = list.filter((item) => item.id !== "notice")
		}

		if (!packageInfo.value?.expenses?.length) {
			list = list.filter((item) => item.id !== "expenses")
		}

		if (!list.length) {
			tabShow.value = false
			resolve(list)
			return
		}

		nextTick(() => {
			let count = 0

			list.map((el) => {
				uni.createSelectorQuery()
					.in(instance)
					.select(`#${el.id}`)
					.boundingClientRect((data) => {
						el.top =
							scroll_top +
							data.top -
							// 这里的 16 其实是每个 card 的间距，是为了保证点击滚动时留出间隙
							(uni.upx2px(186) + uni.upx2px(16) + commonStore.navbarHeight + commonStore.statusBarHeight)

						count++

						if (count === list.length) {
							resolve(list)
						}
					})
					.exec()
			})
		})
	})
}

const handleResourceLoaded = async () => {
	const data = await getDistanceArr()
	tabList.value = data

	if (scrollIntoViewId.value) {
		handleTabClick(tabList.value[0].id)
	}
}

const getTripDetail = async () => {
	const data = await $getTripDetail(tripId.value)
	tripData.value = data
}

onLoad((options) => {
	tripId.value = options.id
	date.value = options.date

	if (options.scene) {
		const scene = decodeURIComponent(options.scene)
		tripId.value = getIdBYScene(scene)
	}

	getTripDetail()
})

watchEffect(async () => {
	if (packageInfo.value.id) {
		const data = await getDistanceArr()
		tabList.value = data

		if (scrollIntoViewId.value) {
			handleTabClick(tabList.value[0].id)
		}
	}
})

onPageScroll(({ scrollTop }) => {
	scroll_top = scrollTop

	// 防止调用 uni.pageScrollTo 方法使页面滚动后，onPageScroll 重复触发
	if (isTabChange.value || !tabList.value.length) return

	if (scrollTop >= baseTop) {
		tabShow.value = true

		const index = tabList.value.findIndex((item) => item.top - scrollTop > 0)

		if (index === -1) {
			currentTabId.value = tabList.value[tabList.value.length - 1].id
		}

		if (index > 0) {
			currentTabId.value = tabList.value[index - 1].id
		}

		if (index === 0) {
			currentTabId.value = tabList.value[index].id
		}
	} else {
		tabShow.value = false
	}
})

onReachBottom(() => {
	if (scroll_top < tabList.value[tabList.value.length - 1].top) {
		currentTabId.value = tabList.value[tabList.value.length - 1].id

		isTabChange.value = true

		timer = setTimeout(() => {
			isTabChange.value = false
			clearTimeout(timer)
		}, 500)
	}
})
</script>

<script>
export default {
	options: { styleIsolation: "shared" },
}
</script>

<style lang="scss" scoped>
@import "../ticket/index.scss";

.page-container {
	padding-bottom: calc(128rpx + 48rpx + env(safe-area-inset-bottom));
}

.tabs-wrap {
	position: fixed;
	left: 0;
	width: 100vw;
	padding: 24rpx 0 12rpx;
	background-color: #fff;
	z-index: 1000;

	.tabs {
		display: flex;
		align-items: center;
		margin-bottom: 12rpx;

		.item {
			position: relative;
			flex: 1;
			padding: 14rpx 0 12rpx;
			font-size: 28rpx;
			color: rgba(0, 0, 0, 0.6);
			line-height: 40rpx;
			text-align: center;

			&.checked {
				font-weight: 600;
				color: rgba(0, 0, 0, 0.9);
				line-height: 44rpx;

				&::before {
					content: "";
					position: absolute;
					left: 50%;
					bottom: 0;
					transform: translateX(-50%);
					width: 36rpx;
					height: 6rpx;
					background-color: #fee038;
					border-radius: 6rpx;
				}
			}
		}
	}

	.scroll-view {
		padding: 0 22rpx;
		white-space: nowrap;
	}

	.line {
		display: flex;
		align-items: center;

		.line-item {
			width: 160rpx;
			padding: 18rpx 48rpx;
			background: #f6f6f9;
			border-radius: 16rpx;
			text-align: center;
			font-size: 24rpx;
			color: #1d2129;
			line-height: 36rpx;
			border: 2rpx solid transparent;

			&.checked {
				background-color: rgba(254, 224, 56, 0.2);
				border: 2rpx solid #fee038;
			}

			&:not(:last-child) {
				margin-right: 24rpx;
			}
		}
	}
}

.order-notice {
	::v-deep {
		.title {
			margin-bottom: 32rpx !important;
		}

		.section {
			margin-bottom: 32rpx !important;
			border-color: #f3f3f3 !important;

			.card-title {
				margin-bottom: 16rpx !important;
				font-size: 28rpx !important;
				color: #1d2129 !important;
				line-height: 40rpx !important;
			}

			&:last-child {
				margin-bottom: 0 !important;
			}
		}
	}
}

.bottom {
	position: fixed;
	bottom: 0;
	left: 0;
	width: 100vw;
	height: calc(128rpx + env(safe-area-inset-bottom));
	height: calc(128rpx + constant(safe-area-inset-bottom));
	padding: 24rpx 24rpx calc(24rpx + env(safe-area-inset-bottom));
	background-color: #fff;
	box-shadow: inset 0rpx 2rpx 0rpx 0rpx #f1f2f5;
	display: flex;
	align-items: center;
	justify-content: space-between;
	z-index: 10;

	.icons {
		display: flex;
		flex-direction: column;
		justify-content: center;
		align-items: center;

		.home-icon {
			width: 40rpx;
			height: 40rpx;
			margin-bottom: 4rpx;
		}

		.text {
			font-size: 24rpx;
			color: #1d2129;
			line-height: 34rpx;
		}
	}

	.btn {
		width: 320rpx;
		height: 80rpx;
		line-height: 80rpx;
		background: #fee038;
		border-radius: 40rpx;
		font-weight: 600;
		font-size: 28rpx;
		color: #1d2129;
		text-align: center;

		&.disabled {
			background-color: #f6f6f9;
		}
	}
}
</style>
